<?php
// +----------------------------------------------------------------------
// | 有小象汇 自研正版源码 赋能开发者
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 http://www.uxphp.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 有小象汇并不是自由软件，未经许可不能去掉有小象汇相关版权
// +----------------------------------------------------------------------
// | Author:  有小象汇
// +----------------------------------------------------------------------

namespace app\services\car;

use app\listener\task\Send;
use app\model\car\CarOrderRerent;
use app\model\car\CarOrderTake;
use app\model\jiyun\Order;
use app\services\BaseServices;
use app\services\order\StoreOrderSuccessServices;
use app\services\pay\PayServices;
use app\services\user\UserMoneyServices;
use app\services\user\UserServices;
use app\services\wechat\WechatUserServices;
use think\exception\ValidateException;
use think\facade\Db;

/**
 * 订单发起支付
 * Class OrderPayServices
 * @package app\services\pay
 */
class OrderPayServices extends BaseServices
{
    /**
     * 支付
     * @var PayServicesorderPay
     */
    protected $payServices;

    public function __construct(PayServices $services)
    {
        $this->payServices = $services;
    }


    /**
     * 订单发起支付
     * @param array $orderInfo
     * @param string $from
     * @param $op_user
     * @param $op_user_type
     * @return array|string
     */
    public function orderPay(array $orderInfo, string $from,$op_user,$op_user_type,$order_type)
    {
        if ($orderInfo['pay_time'] > 0) {
            throw new ValidateException('订单已付款');
        }
        if ($orderInfo['price'] <= 0) {
            throw new ValidateException('无需付款');
        }
        //查询车子是否被占用
        //查询该车型下面是否有车辆可租
        $carInfoServices = app()->make(CarInfoServices::class);
        $carInfoServices->getCarInventory2($orderInfo['type_id'],$orderInfo['start_time'],$orderInfo['end_time'],$orderInfo['car_id']);
        $openid = '';
        $services = app()->make(WechatUserServices::class);
        $openid = $services->uidToOpenid($orderInfo['uid'], $from);
        if (!$openid&&$order_type=='mini') {//小程序支付必须要openid。app支付不用
            throw new ValidateException('无法获取用户openID。无法付款');
        }

        $body = '用户支付'.$orderInfo['order_no'].'订单';
        $ordersn = $orderInfo['order_no'].'-'.$orderInfo['pay_num'];
        $successAction = 'car';
        $wechat_pay = sys_config('pay_weixin_open');
        $allin_pay = sys_config('allinpay_isopen');
        if ($wechat_pay && $allin_pay) {
            $from = 'allinpay';
        } elseif ($allin_pay) {
            $from = 'allinpay';
        } else {
            $from = 'routine';
        }
        $options = [
            'openid' => $openid
        ];
        return $this->payServices->pay($from, $ordersn, $orderInfo, $successAction, $body, $options,$order_type);
    }

    /**
     * 续租订单发起支付
     * @param $rerentInfo
     * @param $from
     * @param $op_user
     * @param $op_user_type
     * @return array|string
     */
    public function rerentPay($rerentInfo,$from,$op_user,$op_user_type){
        if($rerentInfo['pay_time'] > 0) throw new ValidateException('重复支付');
        if($rerentInfo['rerent_price'] <= 0) throw new ValidateException('支付金额不能小于或等于0');
        $openid = '';
        /** @var WechatUserServices $services */
        $services = app()->make(WechatUserServices::class);
        $openid = $services->uidToOpenid($rerentInfo['uid'],$from);
        if(!$openid) throw new ValidateException('无法获取用户openid');
        $body = '用户支付';
        $rerentsn = $rerentInfo['rerent_no'];
        $successAction = 'rerent';
        $wechat_pay = sys_config('pay_weixin_open');
        $allin_pay = sys_config('allinpay_isopen');
        if ($wechat_pay && $allin_pay) {
            $from = 'allinpay';
        } elseif ($allin_pay) {
            $from = 'allinpay';
        } else {
            $from = 'routine';
        }
        $options = [
            'openid' => $openid
        ];
        return $this->payServices->pay($from, $rerentsn, $rerentInfo['rerent_price'], $successAction, $body, $options);
    }

    /**
     * 租车订单余额支付
     * @param array $orderInfo
     * @param $uid
     * @param $op_user
     * @param $op_user_type
     * @return bool[]|string[]
     * @throws \think\db\exception\DbException
     */
    public function yueCarOrderPay(array $orderInfo, $uid, $op_user, $op_user_type)
    {
        if (!$orderInfo) throw new ValidateException('订单不存在!');
        if ($orderInfo['pay_time'] > 0) throw new ValidateException('该订单已支付!');
        /** @var UserServices $services */
        $services = app()->make(UserServices::class);
        $userInfo = $services->getUserInfo($uid);
        if ($userInfo['now_money'] < $orderInfo['price']) return ['status' => 'pay_deficiency', 'msg' => '余额不足' . floatval($orderInfo['pay_price'])];
        $this->transaction(function () use ($services, $orderInfo, $userInfo,$op_user_type,$op_user) {
            $res = false !== $services->bcDec($userInfo['uid'], 'now_money', $orderInfo['price'], 'uid');
            //写入余额记录
            $now_money = bcsub((string)$userInfo['now_money'], (string)$orderInfo['price'], 2);
            $number = $orderInfo['price'];
            /** @var UserMoneyServices $userMoneyServices */
            $userMoneyServices = app()->make(UserMoneyServices::class);
            $res = $res && $userMoneyServices->income('pay_car_order', $userInfo['uid'], $number, $now_money, $orderInfo['id']);
            /** @var StoreOrderSuccessServices $orderServices */
            $orderServices = app()->make(CarOrderServices::class);
            $res = $res && $this->paySuccess($orderInfo, PayServices::YUE_PAY,[],$op_user,$op_user_type);//余额支付成功
            if (!$res) throw new ValidateException('余额支付失败!');
        });
        return ['status' => true];
    }

    /**
     * 续租订单余额支付
     * @param $rerent
     * @param $op_user
     * @param $op_user_type
     * @return bool[]
     */
    public function yueOrderRerentPay($rerent,$op_user,$op_user_type){
        if(!$rerent) throw new ValidateException('未查询到该订单');
        if($rerent['pay_time'] > 0) throw new ValidateException('重复支付');
        if($op_user['now_money'] < $rerent['rerent_price']) throw new ValidateException('余额不足，支付失败');
        /** @var UserServices $services */
        $services = app()->make(UserServices::class);
        $this->transaction(function () use ($services,$rerent,$op_user,$op_user_type){
            $res = false !== $services->bcDec($op_user['uid'],'now_money',$rerent['rerent_price'],'uid');
            // 写入余额记录
            $now_money = bcsub((string)$op_user['now_money'],(string)$rerent['rerent_price'],2);
            $number = $rerent['rerent_price'];
            /** @var UserMoneyServices $userMoneyServices */
            $userMoneyServices = app()->make(UserMoneyServices::class);
            $res = $res && $userMoneyServices->income('pay_order_rerent',$op_user['uid'],$number,$now_money,$rerent['id']);
            $res = $res && $this->payRerentSuccess($rerent,PayServices::YUE_PAY,[],$op_user,$op_user_type);// 余额支付成功
            if(!$res) throw new ValidateException('余额支付失败');
        });
        return ['status'=>true];
    }

    /**
     * 支付成功
     * @param array $orderInfo
     * @param string $paytype
     * @param array $other
     * @param $op_user
     * @param $op_user_type
     * @return bool
     * @throws \think\db\exception\DbException
     */
    public function paySuccess(array $orderInfo, string $paytype = PayServices::WEIXIN_PAY, array $other = [],$op_user,$op_user_type){
        $updata = ['status'=>10,'pay_time'=>time(),'pay_type' => $paytype];
        if ($other && isset($other['trade_no'])) $updata['out_trade_no'] = $other['trade_no'];
        $res1 = Db::name('car_order')->where('id',$orderInfo['id'])->update($updata);
        if($paytype!="yue")$res2 = Db::name('wx_callback_log')->where('transaction_id',$other['trade_no'])->update(['order_id'=>$orderInfo['id']]);
        $resPink = true;
        $res = $res1 && $resPink;
        if ($res){
            /** @var CarOrderTakeServices $orderTake */
            $orderTake = app()->make(CarOrderTakeServices::class);
            $orderTake->payOrderTake($orderInfo['id'],$op_user,$op_user_type);
        }

        $title = '用户支付订单';
        BaseLogServices::addLog($orderInfo['id'],2,$title,$op_user_type,$op_user['uid'],$op_user['nickname'],3);
        //新增订单流水2024年2月25日15:52:17
        BaseLogServices::add_order_flow($orderInfo);
        return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        return false !== $res;
    }

    /**
     * 续租订单支付成功
     * @param $rerentInfo
     * @param string $pay_type
     * @param array $other
     * @param $op_user
     * @param $op_user_type
     * @return bool
     */
    public function payRerentSuccess($rerentInfo,string $pay_type = PayServices::WEIXIN_PAY,array $other = [],$op_user,$op_user_type){
        $update = ['rerent_status'=>20,'pay_time'=>time(),'pay_type'=>$pay_type];
        if($other && isset($other['trade_no'])) $update['rent_trade_no'] = $other['trade_no'];
        $res1 = CarOrderRerent::where('id','=',$rerentInfo['id'])->update($update);
        $title = '用户支付续租订单【'.$rerentInfo['rerent_no'].'】';
        BaseLogServices::addLog($rerentInfo['id'],2,$title,$op_user_type,$op_user['uid'],$op_user['nickname'],19);
        return true;
    }

    /**
     * 支付押金
     * @param $takeInfo
     * @param $from
     * @param $op_user
     * @param $op_user_type
     * @return array|string
     */
    public function depositPay($takeInfo,$from,$op_user,$op_user_type){
        if($takeInfo['deposit_pay_time']) throw new ValidateException('押金已支付');
        if($takeInfo['deposit_fee'] <= 0) throw new ValidateException('押金金额为0，无需支付');
        /** @var WechatUserServices $services */
        $services = app()->make(WechatUserServices::class);
        $openid = $services->uidToOpenid($op_user['uid'],$from);
        if(!$openid) throw new ValidateException('无法获取用户openId，无法付款');
        $body = '用户支付';
        $take_no = $takeInfo['take_no'];
        $successAction = 'deposit';
        $wechat_pay = sys_config('pay_weixin_open');
        $allin_pay = sys_config('allinpay_isopen');
        if($wechat_pay && $allin_pay){
            $from = 'allinpay';
        }elseif($allin_pay){
            $from = 'allinpay';
        }else{
            $from = 'routine';
        }
        $options = [
            'openid' => $openid
        ];
        //$from = routine
        //$take_no =QC2023110314093612
        //$takeInfo['deposit_fee'] =22000.00
        // $successAction=deposit
        //$options = [openid] => oBDvo5M3WqQJeW2_LnN2ZZ_-FfUs
        return $this->payServices->pay($from,$take_no,$takeInfo['deposit_fee'],$successAction,$body,$options);
    }

    /**
     * 押金支付成功后
     * @param $takeInfo
     * @param string $deposit_pay_type
     * @param array $other
     * @param array $op_user
     * @param int $op_user_type
     * @return bool
     */
    public function payDepositSuccess($takeInfo,string $deposit_pay_type = PayServices::WEIXIN_PAY, array $other = [], array $op_user, int $op_user_type){
        $update = [
            'deposit_pay_type'=>$deposit_pay_type,
            'deposit_is_pay'=>1,
            'deposit_pay_time'=>time(),
        ];
        if($other&&isset($other['trade_no'])) $update['deposit_trade_no'] = $other['trade_no'];
        $res = CarOrderTake::where(['id'=>$takeInfo['id']])->update($update);
        $title = '用户支付押金【'.$takeInfo['all_deposit_fee'].'】';
        BaseLogServices::addLog($takeInfo['id'],2,$title,$op_user_type,$op_user['uid']??0,$op_user['nickname']??'',25);
        return true;
    }
}
